/*    
    OpenMheg - A free MHEG-5 library
    Copyright (C) 2008 Dharmesh Malam

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Collections.Generic;
using System.Text;
using Core.Model.Data;

namespace Engine
{
    public class MHEGTuner
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod().DeclaringType );

        private TuneInfo tuning = TuneInfo.Normal;

        public TuneInfo Tuning
        {
            get { return tuning; }
            set { tuning = value; }
        }

        public enum TuneInfo
        {
            Normal=1,
            Quiet
        }

        private WidescreenAlignmentEnum widescreenAlignment = WidescreenAlignmentEnum.CentreCutOut;

        public WidescreenAlignmentEnum WidescreenAlignment
        {
            get { return widescreenAlignment; }
            set { widescreenAlignment = value; }
        }

        public enum WidescreenAlignmentEnum
        {
            CentreCutOut=1,
            Letterbox
        }

        private AspectRatioEnum aspectRatio = AspectRatioEnum.FourThree;

        public AspectRatioEnum AspectRatio
        {
            get { return aspectRatio; }
            set { aspectRatio = value; }
        }

        public enum AspectRatioEnum
        {
            FourThree=1,
            SixteenNine
        }

        private bool subtitlesOn = false;

        public bool SubtitlesOn
        {
            get { return subtitlesOn; }
            set { subtitlesOn = value; }
        }

        private List<ServiceInfo> services = new List<ServiceInfo>();

        public List<ServiceInfo> Services
        {
            get { return services; }
            private set { services = value; }
        }


        public void Initialise ()
        {
            log.Info( "Initialising Tuner..." );
            Tuning = TuneInfo.Normal;
            WidescreenAlignment = WidescreenAlignmentEnum.CentreCutOut;
            AspectRatio = AspectRatioEnum.FourThree;
            SubtitlesOn = false;
        }


        public int GetServiceIndex ( OctetString service )
        {
            ServiceInfo serviceInfo = Resolve( service );
            int index;
            if ( Services.Contains( serviceInfo ) )
                index = Services.IndexOf( serviceInfo );
            else
            {
                Services.Add( serviceInfo );
                index = Services.Count-1;
            }

            log.Info( "GetServiceIndex (GSI):  ("+service+"). @ "+ index );
            return index;

        }

        public void TuneServiceIndex ( int serviceIndex )
        {
            TuneService( Services [serviceIndex] );
            log.Info( "TuneServiceIndex (Tn): Tuning to "+serviceIndex+"("+Services [serviceIndex]+")." );
        }

        public void TuneService ( ServiceInfo service )
        {

        }



        internal int [] GetBasicSI ( int serviceIndex )
        {
            log.Info( "GetBasicServiceIndex (BSI):  ("+Services [serviceIndex]+"). @ "+ Services.Count );
            return Services [serviceIndex].ToArray();
        }

        private ServiceInfo Resolve ( OctetString service )
        {
            ServiceInfo serviceInfo = null;

            if ( service.StartsWith( "dvb:" ) )
            {
                service = service.Remove(0, "dvb://".Length );

                String [] ids = service.ToString().Split( '.' );

                if ( ids.Length == 3 )
                {
                    try
                    {
                        serviceInfo = new ServiceInfo();
                        serviceInfo.NetworkId = int.Parse( ids [0], System.Globalization.NumberStyles.HexNumber );
                        serviceInfo.OriginalNetworkId = int.Parse( ids [0], System.Globalization.NumberStyles.HexNumber );
                        serviceInfo.TransportStreamId =  ids [1] == "" ? null : ( int? ) int.Parse( ids [1], System.Globalization.NumberStyles.HexNumber );
                        serviceInfo.ServiceId = int.Parse( ids [2], System.Globalization.NumberStyles.HexNumber );
                    }
                    catch ( FormatException e )
                    {
                        log.Error( "Resolve: Service index not only consisting of numbers ("+service+").", e );
                    }
                }
                else
                    log.Error( "Resolve: Service index is wrong format:"+service+"." );
            }
            else if ( service.StartsWith( "rec:" ) )
            {

            }
            else
                log.Error( "Resolve: Service index is unreconisable" );


            if ( serviceInfo == null )
                throw new Exception( "Can not Resolve!" );

            return serviceInfo;
        }


    }

    public class ServiceInfo:IEquatable<ServiceInfo>,IEqualityComparer<ServiceInfo>
    {
        private int networkId;

        public int NetworkId
        {
            get { return networkId; }
            set { networkId = value; }
        }

        private int originalNetworkId;

        public int OriginalNetworkId
        {
            get { return originalNetworkId; }
            set { originalNetworkId = value; }
        }
        private int? transportStreamId;

        public int? TransportStreamId
        {
            get { return transportStreamId; }
            set { transportStreamId = value; }
        }
        private int serviceId;

        public int ServiceId
        {
            get { return serviceId; }
            set { serviceId = value; }
        }

        public ServiceInfo () { }
        public ServiceInfo ( int networkId, int originalNetworkId, int transportStreamId, int serviceId )
        {
            this.networkId = networkId;
            this.originalNetworkId = originalNetworkId;
            this.transportStreamId = transportStreamId;
            this.serviceId = serviceId;
        }

        public ServiceInfo ( int networkId, int originalNetworkId, int serviceId )
        {
            this.networkId = networkId;
            this.originalNetworkId = originalNetworkId;
            this.transportStreamId = null;
            this.serviceId = serviceId;

        }

        public int [] ToArray ()
        {
            int [] ret = new int [4];
            ret [0] = NetworkId;
            ret [1] = OriginalNetworkId;
            ret [2] = TransportStreamId ?? ( -1 );
            ret [3] = ServiceId;

            return ret;
        }

        public override string ToString ()
        {
            return "Service Info: "+networkId+"."+originalNetworkId+"."+transportStreamId+"."+serviceId;
        }

        public override int GetHashCode ()
        {
            return ToString().GetHashCode();
        }

        #region IEquatable<ServiceInfo> Members

        public bool Equals ( ServiceInfo other )
        {
            return GetHashCode() == other.GetHashCode();
        }

        #endregion

        #region IEqualityComparer<ServiceInfo> Members

        public bool Equals ( ServiceInfo x, ServiceInfo y )
        {
            return x.GetHashCode() == y.GetHashCode();
        }

        public int GetHashCode ( ServiceInfo obj )
        {
            return obj.GetHashCode();
        }

        #endregion
    }
}


